Skip to content

feat: Add command template to source generators #2646

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

Mee-Tree
Copy link

@Mee-Tree Mee-Tree commented Mar 23, 2025

This PR is an attempt to provide a more flexible configuration for source generator commands through templating.

It should be fully backward compatible with existing source generator configurations.

Implementation Details

  • Support for the following template variables: ${inputs}, ${output}, and ${unmanaged}
  • Variables as standalone arguments expand into multiple arguments (e.g. ${inputs} -> "test1.in" "test2.in")
  • Variables within arguments are joined (e.g. prefix${inputs}suffix -> "prefixtest1.in test2.insuffix")
  • Unknown variables expand to empty strings with a warning message, this behaviour allows for future extension of the variable set
  • Double dollar signs escape template variables (e.g. $${inputs} -> "${inputs}")

This should come in handy for VirtusLab/scala-cli#3583 to eliminate the need for "wrappers" that only reorder the arguments.

@Mee-Tree Mee-Tree force-pushed the sourcegen-template branch from 79c415c to 63d1351 Compare March 23, 2025 21:18
@tgodzik
Copy link
Contributor

tgodzik commented Mar 25, 2025

Thanks for the contribution! Do you have an example of how would a template look like?

@Mee-Tree
Copy link
Author

Thanks for the contribution! Do you have an example of how would a template look like?

Hi! For example, if we have a Config.SourceGenerator like this (some types are simplified for the sake of readability):

Configuration
SourceGenerator(
  sourcesGlobs = SourcesGlobs(
    directory = "/path/to/input", 
    walkDepth = None,
    includes = "glob:*.in",
    excludes = Nil
  ),
  outputDirectory = "/path/to/output",
  command = Nil,
  commandTemplate = List(
    "python3", 
    "-c", 
    "import sys; print(*sys.argv[1:], sep=\"\\n\")", 
    "${inputs}", 
    "$${inputs}", 
    "pref${inputs}suf", 
    "smth", 
    "${unmanaged}", 
    "pref${unmanaged}suf", 
    "${nonexistent}", 
    "$$${output}"
  )
)

The command would be expanded into:

Command
Seq(
 "python3", 
  "-c", 
  "import sys; print(*sys.argv[1:], sep=\"\\n\")", 
  "/path/to/input/test1.in", 
  "/path/to/input/test2.in", 
  "${inputs}", 
  "pref/path/to/input/test1.in /path/to/input/test2.insuf", 
  "smth", 
  "prefsuf", 
  "$/path/to/output"
)

Which, when run, would output (line numbers added for reference):

Output
1 | Warning: Couldn't find substitution for `nonexistent`, consider escaping it with a $.
2 | /path/to/input/test1.in
3 | /path/to/input/test2.in
4 | ${inputs}
5 | pref/path/to/input/test1.in /path/to/input/test2.insuf
6 | smth
7 | prefsuf
8 | $/path/to/output

Let's go through each line:

  • ${inputs} expands to three separate arguments (lines 2-3)
  • $${inputs} expands to ${inputs} (line 4)
  • pref${inputs}suf expands to one argument (line 5)
  • smth is not interpreted in any way and is passed as is (line 6)
  • ${unmanaged} expands to an empty list of arguments because it's Nil
  • pref${unmanaged}suf expands to one argument prefsuf (line 7)
  • ${nonexistent} expands to an empty list of arguments too, but also prints a warning because there's no such variable (line 1)
  • $$${output} expands to one argument containing $ at the beginning (line 8)

Please let me know if you have any further questions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants